#pragma once
#include "Anim.h"
#include "Singleton.h"
#include "Types.h"

#include <fbxfilesdk/fbxfilesdk_nsuse.h>

#include <gl/glew.h>
#include <sfml/Window.hpp>
#include <map>


class GraphicManager : public Singleton<GraphicManager>
{

public:
	struct ModelSkeleBone
	{
		int ID;
		KFbxXMatrix TrasformationMatrix;
		Matrix InvertedMatrix;
	};

	enum AttributeIndex
	{
		VERTEX_INDEX = 0,
		NORMAL_INDEX = 2,
		COLOR_INDEX = 3,
		SECONDARY_COLOR_INDEX = 4,
		FOG_COORD_INDEX = 5,
		BONE_INDEX = 6,
		BONE_WEIGHT_INDEX = 7,
		MULTITEXCOORD0_INDEX = 8,
		MULTITEXCOORD1_INDEX = 9,
		MULTITEXCOORD2_INDEX = 10,
		MULTITEXCOORD3_INDEX = 11,
		MULTITEXCOORD4_INDEX = 12,
		MULTITEXCOORD5_INDEX = 13,
		MULTITEXCOORD6_INDEX = 14,
		MULTITEXCOORD7_INDEX = 15
	};

	void			Init();
	void			Destroy();

	KFbxScene*		GetModel(std::string name);
	ModelData*		GetModelData(std::string name);
	Anim&			GetAnim(std::string name);		
	GLuint			GetTexture(std::string name);
	GLuint			GetShader(std::string name);

	bool			LoadAllTextures();
	bool			LoadAllModels();
	bool			LoadAllAnims();
	bool			LoadAllShaders();

private:
	
	typedef std::map<KString, ModelSkeleBone> BonesMap;
	typedef std::map<std::string, BonesMap> ModelBonesMap;
	typedef std::map<std::string, Anim>	AnimMap;
	typedef std::map<std::string, ModelData>	ModelMap;
	typedef std::map<std::string, GLuint>	ShaderMap;

	KFbxScene*		LoadFile(std::string name);
	void			CreateBonesMap(BonesMap& map, KFbxNode* node, KFbxXMatrix& parentPos, int& totBones);
	ModelSkeleBone	GetBoneID(BonesMap& map, KString boneName);
	BonesMap		GetBoneMap(std::string);
	KFbxXMatrix		GetGeometry(KFbxNode* pNode);

	void			LoadModel(std::string name);	
	void			LoadNode(ModelData& mData, BonesMap& bonesMap, KFbxNode* node);
	void			CreateVBO(ModelData& mData, BonesMap& bonesMap);
	void			DeleteVBO(VBOID* VBOIDs, int totMesh);

	void			LoadAnim(std::string name);
	void			CountBones(KFbxNode* node, int& totBones);
	void			SaveSkinData(Anim& anim, KFbxNode* node, int parentID, KFbxXMatrix& parentPos, const KTime& ktFrame, int currentFrame, int& currentBones);

	void			LoadTexture(std::string name);

	void			LoadShader(std::string name, GLuint& vertID, GLuint& fragID);
	char*			ReadTextFile(const char *fn);

	AnimMap			m_anims;
	ModelMap		m_models;
	ShaderMap		m_shaders;
	ModelBonesMap   m_modelsBones;

	int				meshLoaded;
	int				totMesh;

	typedef std::map<std::string,GLuint>	TextureMap;
	TextureMap m_textures;

	GLuint			m_texture[1];

	KFbxSdkManager* lSdkManager;
};

